package com.ksyun.campus.client;

import com.ksyun.campus.client.domain.StatInfo;
import com.ksyun.campus.client.domain.FileType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;

/**
 * EFileSystem 客户端测试示例
 * 
 * 使用前请确保:
 * 1. ZooKeeper 服务已启动 (localhost:2181)
 * 2. MetaServer 服务已启动
 * 3. DataServer 服务已启动
 */
public class ClientTest {
    private static final Logger logger = LoggerFactory.getLogger(ClientTest.class);
    
    public static void main(String[] args) {
        System.out.println("==================================================");
        System.out.println("           MinFS EasyClient 测试示例");
        System.out.println("==================================================");
        
        // 创建文件系统客户端
        EFileSystem fileSystem = new EFileSystem("testFileSystem");
        
        try {
            // 测试1: 创建目录
            testCreateDirectory(fileSystem);
//
            // 测试2: 创建文件并写入数据
            testCreateFile(fileSystem);

//            // 测试3: 获取集群信息
//            testClusterInfo(fileSystem);
//
//            // 测试4: 读取文件
//            testReadFile(fileSystem);
//
//            // 测试5: 列出目录内容
//            testListDirectory(fileSystem);
////
//            // 测试6: 获取文件状态
//            testGetFileStats(fileSystem);

////            // 测试7: 删除文件和目录
//            testDeleteOperations(fileSystem);

            System.out.println("\n✓ 所有测试完成!");
            
        } catch (Exception e) {
            System.err.println("✗ 测试失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 关闭资源
            fileSystem.close();
            System.out.println("客户端资源已清理");
        }
    }
    
    /**
     * 测试创建目录
     */
    private static void testCreateDirectory(EFileSystem fileSystem) {
        System.out.println("\n--------------------------------------------------");
        System.out.println("测试1: 创建目录");
        System.out.println("--------------------------------------------------");
        
        try {
            // 创建多级目录
            boolean success1 = fileSystem.mkdir("/test");
            System.out.println("创建目录 /test: " + (success1 ? "成功" : "失败"));
            
            boolean success2 = fileSystem.mkdir("/test/data");
            System.out.println("创建目录 /test/data: " + (success2 ? "成功" : "失败"));
            
            boolean success3 = fileSystem.mkdir("/test/logs/2023");
            System.out.println("创建目录 /test/logs/2023: " + (success3 ? "成功" : "失败"));
            
        } catch (Exception e) {
            System.err.println("目录创建失败: " + e.getMessage());
        }
    }
    
    /**
     * 测试创建文件并写入数据
     */
    private static void testCreateFile(EFileSystem fileSystem) {
        System.out.println("\n--------------------------------------------------");
        System.out.println("测试2: 创建文件并写入数据");
        System.out.println("--------------------------------------------------");
        
        try {
            // 创建配置文件
            FSOutputStream configStream = fileSystem.create("/test/config.json");
            String configData = "{\n  \"appName\": \"MinFS Test\",\n  \"version\": \"1.0\",\n  \"debug\": true\n}";
            configStream.write(configData.getBytes());
            configStream.close();
            System.out.println("创建文件 /test/config.json: 成功 (" + configData.length() + " 字节)");
            
            // 创建日志文件
            FSOutputStream logStream = fileSystem.create("/test/logs/2023/app.log");
            String logData = "2023-12-01 10:00:00 INFO Application started\n";
            logData += "2023-12-01 10:00:01 INFO Loading configuration\n";
            logData += "2023-12-01 10:00:02 INFO System ready\n";
            logStream.write(logData.getBytes());
            logStream.close();
            System.out.println("创建文件 /test/logs/2023/app.log: 成功 (" + logData.length() + " 字节)");
            
            // 创建数据文件
            FSOutputStream dataStream = fileSystem.create("/test/data/sample.txt");
            String sampleData = "这是一个测试文件\n包含中文和英文内容\nThis is a test file\n";
            dataStream.write(sampleData.getBytes("UTF-8"));
            dataStream.close();
            System.out.println("创建文件 /test/data/sample.txt: 成功 (" + sampleData.getBytes("UTF-8").length + " 字节)");
            
        } catch (Exception e) {
            System.err.println("文件创建失败: " + e.getMessage());
        }
    }
    
    /**
     * 测试读取文件
     */
    private static void testReadFile(EFileSystem fileSystem) {
        System.out.println("\n--------------------------------------------------");
        System.out.println("测试3: 读取文件");
        System.out.println("--------------------------------------------------");
        
        try {
            // 读取配置文件
            FSInputStream configStream = fileSystem.open("/test/config.json");
            if (configStream != null) {
                byte[] buffer = new byte[1024];
                int bytesRead = configStream.read(buffer);
                if (bytesRead > 0) {
                    String content = new String(buffer, 0, bytesRead);
                    System.out.println("读取 /test/config.json 内容:");
                    System.out.println(content);
                }
                configStream.close();
            } else {
                System.out.println("无法打开文件 /test/config.json");
            }
            
        } catch (Exception e) {
            System.err.println("文件读取失败: " + e.getMessage());
        }
    }
    
    /**
     * 测试列出目录内容
     */
    private static void testListDirectory(EFileSystem fileSystem) {
        System.out.println("\n--------------------------------------------------");
        System.out.println("测试4: 列出目录内容");
        System.out.println("--------------------------------------------------");
        
        try {
            // 列出根目录
            List<StatInfo> rootEntries = fileSystem.listFileStats("/");
            System.out.println("根目录 / 内容:");
            if (rootEntries != null) {
                for (StatInfo entry : rootEntries) {
                    String type = entry.getType() == FileType.Directory ? "目录" : "文件";
                    System.out.println("  " + type + ": " + entry.getPath() + " (大小: " + entry.getSize() + ")");
                }
            }
            
            // 列出测试目录
            List<StatInfo> testEntries = fileSystem.listFileStats("/test");
            System.out.println("\n目录 /test 内容:");
            if (testEntries != null) {
                for (StatInfo entry : testEntries) {
                    String type = entry.getType() == FileType.Directory ? "目录" : "文件";
                    System.out.println("  " + type + ": " + entry.getPath() + " (大小: " + entry.getSize() + ")");
                }
            }
            
        } catch (Exception e) {
            System.err.println("目录列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 测试获取文件状态
     */
    private static void testGetFileStats(EFileSystem fileSystem) {
        System.out.println("\n--------------------------------------------------");
        System.out.println("测试5: 获取文件状态");
        System.out.println("--------------------------------------------------");
        
        try {
            StatInfo configStats = fileSystem.getFileStats("/test/config.json");
            if (configStats != null) {
                System.out.println("文件 /test/config.json 状态:");
                System.out.println("  类型: " + (configStats.getType() == FileType.File ? "文件" : "目录"));
                System.out.println("  大小: " + configStats.getSize() + " 字节");
                System.out.println("  修改时间: " + configStats.getMtime());
                if (configStats.getReplicaData() != null) {
                    System.out.println("  副本数: " + configStats.getReplicaData().size());
                }
            }
            
        } catch (Exception e) {
            System.err.println("获取文件状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 测试获取集群信息
     */
    private static void testClusterInfo(EFileSystem fileSystem) {
        System.out.println("\n--------------------------------------------------");
        System.out.println("测试3: 获取集群信息");
        System.out.println("--------------------------------------------------");
        
        try {
            // 测试获取详细集群信息
            System.out.println("=== 从MetaServer获取详细集群信息 ===");
//            java.util.Map<String, Object> clusterInfo = fileSystem.getClusterInfoFromServer();
//            if (clusterInfo != null) {
//                System.out.println("集群信息获取成功:");
//
//                // 显示Leader信息
//                @SuppressWarnings("unchecked")
//                java.util.Map<String, Object> leader = (java.util.Map<String, Object>) clusterInfo.get("leader");
//                if (leader != null) {
//                    System.out.println("  Leader: " + leader.get("id") + " @ " + leader.get("host") + ":" + leader.get("port"));
//                } else {
//                    System.out.println("  Leader: 未找到");
//                }
//
//                // 显示DataServer信息
//                @SuppressWarnings("unchecked")
//                java.util.List<java.util.Map<String, Object>> dataServers =
//                    (java.util.List<java.util.Map<String, Object>>) clusterInfo.get("dataServers");
//                if (dataServers != null && !dataServers.isEmpty()) {
//                    System.out.println("  DataServers (" + dataServers.size() + " 个):");
//                    for (java.util.Map<String, Object> ds : dataServers) {
//                        long capacity = ((Number) ds.get("capacity")).longValue();
//                        long used = ((Number) ds.get("used")).longValue();
//                        double usagePercent = capacity > 0 ? (used * 100.0 / capacity) : 0;
//                        System.out.printf("    - %s @ %s:%s (容量: %d MB, 已用: %d MB, 使用率: %.1f%%, 最后心跳: %s)%n",
//                                ds.get("dsId"), ds.get("host"), ds.get("port"),
//                                capacity / (1024 * 1024), used / (1024 * 1024),
//                                usagePercent, ds.get("lastSeen"));
//                    }
//                } else {
//                    System.out.println("  DataServers: 未找到");
//                }
//
//                // 显示集群配置信息
//                @SuppressWarnings("unchecked")
//                java.util.Map<String, Object> config = (java.util.Map<String, Object>) clusterInfo.get("config");
//                if (config != null) {
//                    System.out.println("  集群配置:");
//                    System.out.println("    - 副本因子: " + config.get("replicationFactor"));
//                    System.out.println("    - 块大小: " + ((Number) config.get("blockSize")).longValue() / 1024 + " KB");
//                }
//            }
//
//            // 测试获取副本统计信息
//            System.out.println("\n=== 获取副本分布统计 ===");
//            java.util.Map<String, Object> replicaStats = fileSystem.getReplicaStats();
//            if (replicaStats != null) {
//                @SuppressWarnings("unchecked")
//                java.util.List<java.util.Map<String, Object>> byDataServer =
//                    (java.util.List<java.util.Map<String, Object>>) replicaStats.get("byDataServer");
//                if (byDataServer != null && !byDataServer.isEmpty()) {
//                    System.out.println("副本分布统计:");
//                    for (java.util.Map<String, Object> stat : byDataServer) {
//                        System.out.printf("  - %s: 主块=%d, 副本块=%d, 总计=%d%n",
//                                stat.get("dsId"), stat.get("primaryBlocks"),
//                                stat.get("replicaBlocks"), stat.get("total"));
//                    }
//                    System.out.println("统计时间: " + replicaStats.get("ts"));
//                } else {
//                    System.out.println("副本统计: 暂无数据");
//                }
//            }
//
            // 测试从ZooKeeper获取集群信息（原有功能）
            System.out.println("\n=== 从ZooKeeper获取基础集群信息 ===");
            com.ksyun.campus.client.domain.ClusterInfo zkClusterInfo = fileSystem.getClusterInfo();
            if (zkClusterInfo != null) {
                System.out.println("ZooKeeper集群信息:");
                if (zkClusterInfo.getMasterMetaServer() != null) {
                    System.out.println("  Master MetaServer: " + zkClusterInfo.getMasterMetaServer().getHost() + 
                            ":" + zkClusterInfo.getMasterMetaServer().getPort());
                }
                
                // 显示所有MetaServer实例（按ZooKeeper中的名称）
                if (zkClusterInfo.getMetaServers() != null && !zkClusterInfo.getMetaServers().isEmpty()) {
                    System.out.println("  MetaServer实例 (" + zkClusterInfo.getMetaServers().size() + " 个):");
                    for (com.ksyun.campus.client.domain.MetaServerMsg ms : zkClusterInfo.getMetaServers()) {
                        String instanceName = ms.getInstanceId() != null ? ms.getInstanceId() : "unknown";
                        System.out.println("    - " + instanceName + ": " + ms.getHost() + ":" + ms.getPort());
                    }
                } else if (zkClusterInfo.getSlaveMetaServer() != null) {
                    // 如果没有metaServers信息，回退到显示slave
                    System.out.println("  Slave MetaServer: " + zkClusterInfo.getSlaveMetaServer().getHost() + 
                            ":" + zkClusterInfo.getSlaveMetaServer().getPort());
                }
                
                if (zkClusterInfo.getDataServers() != null && !zkClusterInfo.getDataServers().isEmpty()) {
                    System.out.println("  DataServers (" + zkClusterInfo.getDataServers().size() + " 个):");
                    for (com.ksyun.campus.client.domain.DataServerMsg ds : zkClusterInfo.getDataServers()) {
                        System.out.println("    - " + ds.getHost() + ":" + ds.getPort());
                    }
                }
            }
            
        } catch (Exception e) {
            System.err.println("获取集群信息失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    /**
     * 测试删除操作
     */
    private static void testDeleteOperations(EFileSystem fileSystem) {
        System.out.println("\n--------------------------------------------------");
        System.out.println("测试7: 删除文件和目录");
        System.out.println("--------------------------------------------------");
        
        try {
            // 删除文件
            boolean deleteFile = fileSystem.delete("/test/config.json");
            System.out.println("删除文件 /test/config.json: " + (deleteFile ? "成功" : "失败"));
            
            // 删除目录（递归）
            boolean deleteDir = fileSystem.delete("/test/data");
            System.out.println("删除目录 /test/data: " + (deleteDir ? "成功" : "失败"));
            
        } catch (Exception e) {
            System.err.println("删除操作失败: " + e.getMessage());
        }
    }
}
